﻿using EFFC.Frame.Net.Module.Extend.EWRA.Attributes;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using EFFC.Extends.LinqDLR2SQL;
using EFFC.Frame.Net.Unit.DB;
using EFFC.Frame.Net.Base.Data.Base;
using EFFC.Frame.Net.Module.Extend.EWRA.Attributes.Validation;
using EFFC.Frame.Net.Base.Common;
using EFFC.Frame.Net.Base.Data;
using EFFC.Frame.Net.Module.Business.Datas;
using ICPFrameLib.Business;
using ICPFrameLib.Attributes;
using EFFC.Frame.Net.Base.Constants;
using System.Text.RegularExpressions;
using XHRPMIS.Common;
using EFFC.Frame.Net.Unit.DB.Parameters;
using System.IO;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using NPOI.SS.Util;
using System.Text;
using System.Drawing;
using ICPFrameLib.Common;

namespace XHRPMIS.Business.v1._0
{
    public class SingleTableOP : MyRestLogic
    {
        MetaDataSet mds = new MetaDataSet();
        RefExpress ref_express = new RefExpress();
        [EWRARouteDesc("获取单表的设定信息，含表头、查询条件")]
        [EWRARoute("get", "/s_table/{id}/info")]
        [EWRAAddInput("id", "string", "动态功能的uid", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, false)]
        [EWRAOutputDesc("返回结果", @"如果是授权无效的情况下，返回400错，其它情况的返回结果集（状态为200）如下：{
code:'success-成功，failed-失败',
msg:'提示信息',
data:{
        uid:'uid',
        name:'单表操作-介绍名称',
        desc:'单表操作-描述',
        search:[
            {
                search_id:'查询条件组编号',
                search_desc:'查询条件组描述',
                tips:'查询条件组标签提示说明',
                is_required:'必输检查标记，界面针对该标记显示必输标记',
                sort_num:'栏位排序编号',
                memo:'备注',
                conditions:[
                    {
                        condition_id:'条件编号',
                        op:'查询条件操作方式：like-模糊查询，=-精确查询，>-大于,>=-大于等于，<-小于，<=-小于等于',
                        column_name:'栏位名称',
                        parameter_name:'相关的参数名称,做查询条件时页面传入的参数名称',
                        tips:'提示说明',
                        check_required:'必输检查',
                        check_regex:'正则表达式检查',
                        ui_type:'UI类型，有以下几种：
                                Input-输入框（默认）;
                                Select-下拉选框;
                                Pop:弹出框（显示勾选列表）;
                                Calendar:日历控件;
                                Switch:左右滑动开关;
                                RichText:富文本编辑器;
                                File:文件，点击后弹框显示上传文件控件和下载按钮;
                                Picture:点击后弹框显示上传文件控件和显示图片;
                                PicXY:点击弹出的图片中的任意位置，返回该位置的X、Y轴坐标，返回值格式为:{x坐标},{y坐标};
                                MapXY:点击弹出的地图中的任意位置，返回该位置的经纬度，返回值格式为:{经度},{纬度}',
                    }
                ]
            }
        ],
        columns:[
            {
                column_name:'栏位名称',
                column_desc:'表头名称',
                max_length:'允许输入的最大长度',
                tips:'标签提示说明',
                check_required:'必输检查',
                check_regex:'正则表达式检查',
                sort_num:'栏位排序编号',
                ui_type:'UI类型，有以下几种：
                        Input-输入框（默认）;
                        Select-下拉选框;
                        Pop:弹出框（显示勾选列表）;
                        Calendar:日历控件;
                        Switch:左右滑动开关;
                        RichText:富文本编辑器;
                        File:文件，点击后弹框显示上传文件控件和下载按钮;
                        Picture:点击后弹框显示上传文件控件和显示图片;
                        PicXY:点击弹出的图片中的任意位置，返回该位置的X、Y轴坐标，返回值格式为:{x坐标},{y坐标};
                        MapXY:点击弹出的地图中的任意位置，返回该位置的经纬度，返回值格式为:{经度},{纬度}',
                memo:'备注'
            }
        ],
        events:[{
            no:'事件编号',
            name:'事件名称',
            category:'事件分类，相关说明参见《事件扩展设计说明.docx》',
            type:'事件类型，相关说明参见《事件扩展设计说明.docx》',
            at:'事件触发时机，相关说明参见《事件扩展设计说明.docx》',
            desc:'事件描述'
        }],
        row_events:[{
            no:'事件编号',
            name:'事件名称',
            category:'事件分类，相关说明参见《事件扩展设计说明.docx》',
            type:'事件类型，相关说明参见《事件扩展设计说明.docx》',
            at:'事件触发时机，相关说明参见《事件扩展设计说明.docx》',
            desc:'事件描述'
        }]
    }
}")]
        object GetSettingInfo(string id)
        {
            SetCacheEnable(false);
            var up = DB.NewMetaUnitParameter();
            var s = from t in DB.LamdaTable(up, "EXTEND_SINGLETABLE_OP", "a")
                    where (t.s_uid == id || t.S_Name == id)
                    select t;
            var list = s.GetQueryList(up);
            if (list.Count <= 0)
            {
                return new
                {
                    code = "failed",
                    msg = "设定资料不存在"
                };
            }
            dynamic info = list.First();
            if (!IsValidBy("没有访问权限", () =>
            {
                return IsAuth(ComFunc.nvl(info.ActionAuth));
            }))
            {
                return null;
            }
            var metainfo = (from t in DB.LamdaTable(up, "EXTEND_METADATA", "a")
                            where t.MetaUID == info.MetaUID && t.IsCreated == 1
                            select new
                            {
                                table_name = t.MetaName
                            }).GetQueryList(up);
            if (metainfo.Count <= 0)
            {
                return new
                {
                    code = "failed",
                    msg = "元数据表不存在，无法继续进行操作"
                };
            }
            #region 抓取设定的条件列表
            var searchlist = (from t in DB.LamdaTable(up, "EXTEND_SINGLETABLE_OP_SEARCH", "a")
                              where t.S_UID == info.S_UID
                              select new
                              {
                                  search_id = t.S_SearchID,
                                  search_desc = t.S_SearchDesc,
                                  tips = t.S_Tips,
                                  is_required = t.S_IsRequired,
                                  memo = t.S_Memo,
                                  sort_num = t.S_Sort_Num
                              }).GetQueryList(up);
            var conditionlist = (from t in DB.LamdaTable(up, "EXTEND_SINGLETABLE_OP_CONDITIONS", "a")
                                 join t2 in DB.LamdaTable(up, "EXTEND_METADATA_COLUMNS", "b") on t.S_ColumnName equals t2.MetaColumnName
                                 join t3 in DB.LamdaTable(up, "EXTEND_METADATA_DATATYPE", "c").LeftJoin() on t2.MetaDataType equals t3.DataType
                                 where t.S_UID == info.S_UID && t2.MetaUID == info.MetaUID
                                 select new
                                 {
                                     search_id = t.S_SearchID,
                                     condition_id = t.S_ConditionID,
                                     op = t.S_ConditionOP,
                                     column_name = t.S_ColumnName,
                                     parameter_name = t.S_Parameter,
                                     tips = t.S_Tips,
                                     check_required = t.S_Check_Required,
                                     check_regex = t.S_Check_Regex,
                                     ui_type = t3.UI_TYPE,
                                     reference = t2.MetaReference
                                 }).GetQueryList(up);
            var conditions = from tt in conditionlist
                             select new
                             {
                                 tt.search_id,
                                 tt.condition_id,
                                 tt.op,
                                 tt.column_name,
                                 tt.parameter_name,
                                 tt.tips,
                                 tt.check_required,
                                 tt.check_regex,
                                 sort_num = new string[] { "<", "<=" }.Contains((string)ComFunc.nvl(tt.op)) ? 99 : 0,
                                 tt.ui_type,
                                 tt.reference
                             };
            var search = from t in searchlist
                         orderby IntStd.IsNotIntThen(t.sort_num)
                         select new
                         {
                             t.search_id,
                             t.search_desc,
                             t.tips,
                             is_required = BoolStd.IsNotBoolThen(t.is_required, false),
                             sort_num = IntStd.IsNotIntThen(t.sort_num),
                             t.memo,
                             conditions = conditionlist.Where(w => w.search_id == t.search_id)
                                            .OrderBy(o => o.sort_num)
                                            .Select((d) =>
                                            {
                                                var ui_type = d.ui_type;
                                                RefExpress.RefExpressResult reference = ref_express.ParseExpress(ComFunc.nvl(d.reference));
                                                if (reference != null && !string.IsNullOrEmpty(reference.TableName))
                                                {
                                                    if (!new string[] { "MapXY", "PicXY" }.Contains((string)d.ui_type))
                                                    {
                                                        if (reference.ShowColumns.Count > 1)
                                                        {
                                                            ui_type = "Pop";
                                                        }
                                                        else
                                                        {
                                                            ui_type = "Select";
                                                        }
                                                    }
                                                }
                                                return new
                                                {
                                                    d.condition_id,
                                                    d.op,
                                                    d.column_name,
                                                    d.parameter_name,
                                                    d.tips,
                                                    check_required = BoolStd.IsNotBoolThen(d.check_required, false),
                                                    d.check_regex,
                                                    ui_type
                                                };
                                            })
                         };
            #endregion
            #region 抓取显示栏位设定
            var columnlist = (from t in DB.LamdaTable(up, "EXTEND_SINGLETABLE_OP_COLUMNS", "a")
                              join t2 in DB.LamdaTable(up, "EXTEND_METADATA_COLUMNS", "b") on t.S_ColumnName equals t2.MetaColumnName
                              join t3 in DB.LamdaTable(up, "EXTEND_METADATA_DATATYPE", "c").LeftJoin() on t2.MetaDataType equals t3.DataType
                              where t.S_UID == info.S_UID && t2.MetaUID == info.MetaUID
                              select new
                              {
                                  column_name = t.S_ColumnName,
                                  column_desc = t.S_ColumnDesc,
                                  max_length = t.S_ColumnMaxSize,
                                  tips = t.S_Tips,
                                  check_required = t.S_Check_Required,
                                  check_regex = t.S_Check_Regex,
                                  sort_num = t.S_Sort_Num,
                                  memo = t.S_Memo,
                                  data_type = t2.MetaDataType,
                                  reference = t2.MetaReference,
                                  is_allow_empty = t2.MetaAllowEmpty,
                                  ui_type = t3.UI_TYPE
                              }).GetQueryList(up);
            var columns = columnlist.OrderBy(d => d.sort_num).Select((d) =>
            {
                var dobj = FrameDLRObject.CreateInstance(FrameDLRFlags.SensitiveCase);
                dobj.column_name = d.column_name;
                dobj.column_desc = d.column_desc;
                dobj.max_length = IntStd.IsNotIntThen(d.max_length, -1);
                dobj.tips = d.tips;
                //优先判断是否允许为空，不许为空的时候强制进行检核，否则以设定值来判断
                dobj.check_required = BoolStd.IsNotBoolThen(d.is_allow_empty, true) ? BoolStd.IsNotBoolThen(d.check_required, false) : true;
                dobj.check_regex = d.check_regex;
                dobj.memo = d.memo;
                dobj.sort_num = d.sort_nuk;
                dobj.ui_type = d.ui_type;
                RefExpress.RefExpressResult reference = ref_express.ParseExpress(ComFunc.nvl(d.reference));
                if (reference != null && !string.IsNullOrEmpty(reference.TableName))
                {
                    if (!new string[] { "MapXY", "PicXY" }.Contains((string)dobj.ui_type))
                    {
                        if (reference.ShowColumns.Count > 1)
                        {
                            dobj.ui_type = "Pop";
                        }
                        else
                        {
                            dobj.ui_type = "Select";
                        }
                    }
                }
                return dobj;
            });

            #endregion
            #region 抓取事件设定
            //获取事件信息
            var eventslist = (from t in DB.LamdaTable(up, "EXTEND_EVENTS", "a")
                              join t2 in DB.LamdaTable(up, "EXTEND_SINGLETABLE_OP_EVENTS", "b") on t.EventNo equals t2.S_Event_No
                              where t2.S_UID == info.S_UID
                              select new
                              {
                                  no = t.EventNo,
                                  name = t.EventName,
                                  category = t.EventCategory,
                                  type = t.EventType,
                                  at = t.EventAt,
                                  desc = t.EventDesc
                              }).GetQueryList(up);
            #endregion
            return new
            {
                code = "success",
                msg = "",
                name = info.S_Name,
                desc = info.S_Desc,
                search,
                columns,
                events = eventslist.Where(w => !ComFunc.nvl(w.type).StartsWith("Row")),
                row_events = eventslist.Where(w => ComFunc.nvl(w.type).StartsWith("Row"))
            };
        }
        [EWRARouteDesc("获取下拉框或pop的内容")]
        [EWRARoute("patch", "/s_table/pop/{id}/{column_name}")]
        [EWRAAddInput("id", "string", "动态功能的uid", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, false)]
        [EWRAAddInput("column_name", "string", "指定栏位的名称", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, false)]
        [EWRAAddInput("this_data", "string", @"页面上当前编辑的行资料，先采用url编码，再采用base64编码，原数据格式:
{
    column_name1:'值，如果为file、picture类型则值的格式内容为上传后的文件路径',
    column_name2:'值，如果为file、picture类型则值的格式内容为上传后的文件路径',
    .....
    column_nameN:'值，如果为file、picture类型则值的格式内容为上传后的文件路径',
}", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, true)]
        [EWRAOutputDesc("返回结果", @"如果是授权无效的情况下，返回400错，其它情况的返回结果集（状态为200）如下：{
code:'success-成功，failed-失败',
msg:'提示信息',
column_value:'表示选中值的栏位名称,如果为空，则表示接受UI设定的任意值',
column_show:[{
    column_name:'栏位名称',
    column_desc:'栏位中文名称',
    ui_type:'UI控件类型'
}],
data:[结果集]")]
        object GetPop(string id, string column_name)
        {
            SetCacheEnable(false);
            var up = DB.NewMetaUnitParameter();
            var s = from t in DB.LamdaTable(up, "EXTEND_SINGLETABLE_OP", "a")
                    where (t.s_uid == id || t.S_Name == id)
                    select t;
            var list = s.GetQueryList(up);
            if (list.Count <= 0)
            {
                return new
                {
                    code = "failed",
                    msg = "设定资料不存在"
                };
            }
            dynamic info = list.First();
            if (!IsValidBy("没有访问权限", () =>
            {
                return IsAuth(ComFunc.nvl(info.ActionAuth));
            }))
            {
                return null;
            }
            var metainfo = (from t in DB.LamdaTable(up, "EXTEND_METADATA_COLUMNS", "a")
                            where t.MetaUID == info.MetaUID && t.MetaColumnName == column_name
                            select new
                            {
                                reference = t.MetaReference
                            }).GetQueryList(up);
            if (metainfo.Count <= 0)
            {
                return new
                {
                    code = "failed",
                    msg = "相关栏位资料不存在，无法继续进行操作"
                };
            }
            var column_ref = ComFunc.nvl(metainfo.First().GetValue("reference"));
            if (column_ref == "")
            {
                return new
                {
                    code = "failed",
                    msg = "相关栏位缺少关联数据，无法继续进行操作"
                };
            }

            var refResult = ref_express.ParseExpress(column_ref);
            if (refResult == null)
            {
                return new
                {
                    code = "failed",
                    msg = "相关栏位关联信息描述存在错误，无法继续进行操作"
                };
            }
            var data_str = ComFunc.nvl(PostDataD.this_data).Replace(" ", "+");
            var this_data_base64str = ComFunc.IsBase64Then(data_str);
            string this_data_str = ComFunc.UrlDecode(this_data_base64str);
            var this_data = FrameDLRObject.IsJsonThen(this_data_str);
            if (data_str != "" && (this_data_str == "" || this_data == null))
            {
                return new
                {
                    code = "failed",
                    msg = "当前行资料格式不正确"
                };
            }


            var data = DB.Excute(up, refResult.ToDBExpress(this_data), false).QueryData<FrameDLRObject>();
            //获取column_show的中文名称
            var metacolumns = (from t in DB.LamdaTable(up, "EXTEND_METADATA", "a")
                               join t2 in DB.LamdaTable(up, "EXTEND_METADATA_COLUMNS", "b") on t.MetaUID equals t2.MetaUID
                               join t3 in DB.LamdaTable(up, "EXTEND_METADATA_DATATYPE", "c").LeftJoin() on t2.MetaDataType equals t3.DataType
                               where t.MetaName == refResult.TableName
                               select new
                               {
                                   column_name = t2.MetaColumnName,
                                   column_desc = t2.MetaColumnDesc,
                                   ui_type = t3.UI_TYPE
                               }).GetQueryList(up);
            var dictable = (from t in DB.LamdaTable(up, "EXTEND_DICTIONARY_TABLE", "a")
                            where t.DIC_Name == refResult.TableName
                            select new
                            {
                                t.IsTree
                            }
                              ).GetQueryList(up);
            if (dictable.Count > 0)
            {
                metacolumns.Add(FrameDLRObject.CreateInstance(@"{
column_name:'code',
column_desc:'编号',
ui_type:'Input'
}"));
                metacolumns.Add(FrameDLRObject.CreateInstance(@"{
column_name:'value',
column_desc:'值',
ui_type:'Input'
}"));
                if (BoolStd.IsNotBoolThen(dictable.First().GetValue("IsTree")))
                {
                    metacolumns.Add(FrameDLRObject.CreateInstance(@"{
column_name:'p_code',
column_desc:'父节点编号编号',
ui_type:'Input'
}"));
                    metacolumns.Add(FrameDLRObject.CreateInstance(@"{
column_name:'level',
column_desc:'层级',
ui_type:'Input'
}"));
                }
            }
            var column_map = metacolumns.ToDictionary(k => k.GetValue("column_name"), v => new { v.column_desc, v.ui_type });
            return new
            {
                code = "success",
                msg = "",
                column_value = refResult.KeyColumn,
                column_show = from t in refResult.ShowColumns
                              select new
                              {
                                  column_name = t,
                                  column_desc = column_map.ContainsKey(t) ? column_map[t].column_desc : "",
                                  ui_type = column_map.ContainsKey(t) ? column_map[t].ui_type : "Input"
                              },
                data
            };
        }
        [EWRARouteDesc("获取ui_type为picxy的弹出框内容")]
        [EWRARoute("patch", "/s_table/pop/picxy/{id}/{column_name}")]
        [EWRAAddInput("id", "string", "动态功能的uid", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, false)]
        [EWRAAddInput("column_name", "string", "指定栏位的名称", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, false)]
        [EWRAAddInput("this_data", "string", @"页面上当前编辑的行资料，先采用url编码，再采用base64编码，原数据格式:
{
    column_name1:'值，如果为file、picture类型则值的格式内容为上传后的文件路径',
    column_name2:'值，如果为file、picture类型则值的格式内容为上传后的文件路径',
    .....
    column_nameN:'值，如果为file、picture类型则值的格式内容为上传后的文件路径',
}", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, true)]
        [EWRAOutputDesc("返回结果", @"如果是授权无效的情况下，返回400错，其它情况的返回结果集（状态为200）如下：{
code:'success-成功，failed-失败',
msg:'提示信息',
filetype:'文件的content-type类型'
filename:'文件名称',
filelength:'文件长度',
file:'文件内容，采用base64加密'
}")]
        object GetPicXYPop(string id, string column_name)
        {
            SetCacheEnable(false);
            var up = DB.NewMetaUnitParameter();
            var s = from t in DB.LamdaTable(up, "EXTEND_SINGLETABLE_OP", "a")
                    where (t.s_uid == id || t.S_Name == id)
                    select t;
            var list = s.GetQueryList(up);
            if (list.Count <= 0)
            {
                return new
                {
                    code = "failed",
                    msg = "设定资料不存在"
                };
            }
            dynamic info = list.First();
            if (!IsValidBy("没有访问权限", () =>
            {
                return IsAuth(ComFunc.nvl(info.ActionAuth));
            }))
            {
                return null;
            }
            var metainfo = (from t in DB.LamdaTable(up, "EXTEND_METADATA_COLUMNS", "a")
                            where t.MetaUID == info.MetaUID && t.MetaColumnName == column_name
                            select new
                            {
                                reference = t.MetaReference
                            }).GetQueryList(up);
            if (metainfo.Count <= 0)
            {
                return new
                {
                    code = "failed",
                    msg = "相关栏位资料不存在，无法继续进行操作"
                };
            }
            var column_ref = ComFunc.nvl(metainfo.First().GetValue("reference"));
            if (column_ref == "")
            {
                return new
                {
                    code = "failed",
                    msg = "相关栏位缺少关联数据，无法继续进行操作"
                };
            }

            var refResult = ref_express.ParseExpress(column_ref);
            if (refResult == null)
            {
                return new
                {
                    code = "failed",
                    msg = "相关栏位关联信息描述存在错误，无法继续进行操作"
                };
            }
            var data_str = ComFunc.nvl(PostDataD.this_data).Replace(" ", "+");
            var this_data_base64str = ComFunc.IsBase64Then(data_str);
            string this_data_str = ComFunc.UrlDecode(this_data_base64str);
            var this_data = FrameDLRObject.IsJsonThen(this_data_str);
            if (data_str != "" && (this_data_str == "" || this_data == null))
            {
                return new
                {
                    code = "failed",
                    msg = "当前行资料格式不正确"
                };
            }

            var data = DB.Excute(up, refResult.ToDBExpress(this_data), false);
            if (data.QueryTable.RowLength <= 0)
            {
                return new
                {
                    code = "failed",
                    msg = "无法查到指定图片数据"
                };
            }
            //只抓取第一行资料的第一个栏位的值
            var result = FileHelper.DoDownLoad(ComFunc.nvl(data.QueryTable[0, 0]));
            return result;
        }
        [EWRARouteDesc("列表查询")]
        [EWRARoute("get", "/s_table/{id}")]
        [EWRAAddInput("id", "string", "动态功能的uid", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, false)]
        [EWRAAddInput("limit", "int", "每页笔数", "默认为10", EFFC.Frame.Net.Base.Constants.RestInputPosition.QueryString, true)]
        [EWRAAddInput("page", "int", "跳到指定页数", "默认为1", EFFC.Frame.Net.Base.Constants.RestInputPosition.QueryString, true)]
        [EWRAAddInput("xxx", "string", "动态功能中设定的查询条件参数", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.QueryString, true)]
        [EWRAOutputDesc("返回结果", @"如果是授权无效的情况下，返回400错，其它情况的返回结果集（状态为200）如下：{
code:'success-成功，failed-失败',
msg:'提示信息',
total_count:'总笔数',
page:'当前页数',
total_page:'总页数',
limit:'每页笔数',
data:[数据集]
}")]
        public object QueryList(string id)
        {
            SetCacheEnable(false);
            var up = DB.NewMetaUnitParameter();
            var s = from t in DB.LamdaTable(up, "EXTEND_SINGLETABLE_OP", "a")
                    where (t.s_uid == id || t.S_Name == id)
                    select t;
            var list = s.GetQueryList(up);
            if (list.Count <= 0)
            {
                return new
                {
                    code = "failed",
                    msg = "设定资料不存在"
                };
            }
            dynamic info = list.First();
            if (!IsValidBy("没有访问权限", () =>
            {
                return IsAuth(ComFunc.nvl(info.ActionAuth));
            }))
            {
                return null;
            }

            Func<object> invoke = () =>
                  {
                      var metainfo = (from t in DB.LamdaTable(up, "EXTEND_METADATA", "a")
                                      where t.MetaUID == info.MetaUID && t.IsCreated == 1
                                      select new
                                      {
                                          table_name = t.MetaName
                                      }).GetQueryList(up);
                      if (metainfo.Count <= 0)
                      {
                          return new
                          {
                              code = "failed",
                              msg = "元数据表不存在，无法继续进行操作"
                          };
                      }

                      var table_name = ComFunc.nvl(metainfo.First().GetValue("table_name"));
                      //组织查询表达式
                      FrameDLRObject express = FrameDLRObject.CreateInstance($@"{{
$acttype : 'QueryByPage',
$orderby : 'sort_no',
$table:'{table_name}',
sort_no:true
                }}", EFFC.Frame.Net.Base.Constants.FrameDLRFlags.SensitiveCase);
                      #region 获取查询条件信息
                      var conditionlist = (from t in DB.LamdaTable(up, "EXTEND_SINGLETABLE_OP_CONDITIONS", "a")
                                           join t2 in DB.LamdaTable(up, "EXTEND_METADATA_COLUMNS", "b").LeftJoin() on t.S_ColumnName equals t2.MetaColumnName
                                           where t.S_UID == info.S_UID && t2.MetaUID == info.MetaUID
                                           select new
                                           {
                                               op = t.S_ConditionOP,
                                               column_name = t.S_ColumnName,
                                               parameter_name = t.S_Parameter,
                                               data_type = t2.MetaDataType
                                           }).GetQueryList(up);
                      FrameDLRObject where_express = FrameDLRObject.CreateInstance(FrameDLRFlags.SensitiveCase);
                      foreach (dynamic citem in conditionlist)
                      {
                          if (ComFunc.nvl(QueryString[citem.parameter_name]) == "") continue;
                          var value = ConvertConditionValue(citem.data_type, ComFunc.nvl(QueryString[citem.parameter_name]));
                          FrameDLRObject exp = where_express.GetValue(citem.column_name);
                          if (exp == null)
                          {
                              exp = FrameDLRObject.CreateInstance(FrameDLRFlags.SensitiveCase);
                          }
                          switch (citem.op)
                          {
                              case "like":
                                  exp.SetValue("$like", value);
                                  where_express.SetValue(citem.column_name, exp);
                                  break;
                              case "=":
                                  where_express.SetValue(citem.column_name, value);
                                  break;
                              case ">":
                                  exp.SetValue("$gt", value);
                                  where_express.SetValue(citem.column_name, exp);
                                  break;
                              case ">=":
                                  exp.SetValue("$gte", value);
                                  where_express.SetValue(citem.column_name, exp);
                                  break;
                              case "<":
                                  exp.SetValue("$lt", value);
                                  where_express.SetValue(citem.column_name, exp);
                                  break;
                              case "<=":
                                  exp.SetValue("$lte", value);
                                  where_express.SetValue(citem.column_name, exp);
                                  break;
                          }
                      }
                      if (where_express.Items.Count > 0)
                      {
                          express.SetValue("$where", where_express);
                      }
                      #endregion
                      #region 组织select栏位
                      var columns = (from t in DB.LamdaTable(up, "EXTEND_SINGLETABLE_OP_COLUMNS", "a")
                                     where t.S_UID == info.S_UID
                                     select new
                                     {
                                         column_name = t.S_ColumnName
                                     }).GetQueryList(up);
                      foreach (dynamic item in columns)
                      {
                          express.SetValue(item.column_name, true);
                      }
                      //抓取pk栏位
                      var pkcolumns = (from t in DB.LamdaTable(up, "EXTEND_METADATA_COLUMNS", "a")
                                       where t.MetaUID == info.MetaUID && t.MetaIsPK == 1
                                       select new
                                       {
                                           column_name = t.MetaColumnName
                                       }).GetQueryList(up);
                      foreach (dynamic item in pkcolumns)
                      {
                          express.SetValue(item.column_name, true);
                      }
                      #endregion
                      var result = DB.Excute(up, express, false);

                      return new
                      {
                          code = "success",
                          msg = "",
                          total_count = result.TotalRow,
                          page = result.CurrentPage,
                          total_page = result.TotalPage,
                          limit = result.Count_Of_OnePage,
                          data = result.QueryData<FrameDLRObject>().Select((d) =>
                          {
                              FrameDLRObject dobj = (FrameDLRObject)d;
                              dobj.Remove("RowNumber");
                              //时间类型需要转string
                              foreach (var item in dobj.Items)
                              {
                                  if (item.Value is DateTime)
                                  {
                                      dobj.SetValue(item.Key, DateTimeStd.IsDateTimeThen(item.Value, "yyyy-MM-dd HH:mm:ss"));
                                  }
                              }
                              return dobj;
                          })
                      };
                  };
            return ParentEventCall(up, info.s_uid, "E01", invoke);
        }
        [EWRAEmptyValid("data")]
        [EWRARouteDesc("新增数据")]
        [EWRARoute("post", "/s_table/{id}")]
        [EWRAAddInput("id", "string", "元数据表uid", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, false)]
        [EWRAAddInput("data", "array", @"待新增的数据列表，如果为file、picture类型,则需要先进行上传，再传入返回的文件路径，格式:
[
{
    column_name1:'值，如果为file、picture类型则值的格式内容为上传后的文件路径',
    column_name2:'值，如果为file、picture类型则值的格式内容为上传后的文件路径',
    .....
    column_nameN:'值，如果为file、picture类型则值的格式内容为上传后的文件路径',
}
]
", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, false)]
        [EWRAOutputDesc("返回结果", @"{
code:'success-成功，failed-失败',
msg:'提示信息'
}")]
        public object Insert(string id)
        {
            var data = PostDataD.data;

            if (!(data is IEnumerable<object>))
                return new
                {
                    code = "failed",
                    msg = "参数格式不正确",
                };

            var metaup = DB.NewMetaUnitParameter();
            var up = DB.NewDBUnitParameter();
            var s = from t in DB.LamdaTable(up, "EXTEND_SINGLETABLE_OP", "a")
                    where (t.s_uid == id || t.S_Name == id)
                    select t;
            var list = s.GetQueryList(up);
            if (list.Count <= 0)
            {
                return new
                {
                    code = "failed",
                    msg = "设定资料不存在"
                };
            }
            dynamic info = list.First();
            if (!IsValidBy("没有访问权限", () =>
            {
                return IsAuth(ComFunc.nvl(info.ActionAuth));
            }))
            {
                return null;
            }

            var datalist = (IEnumerable<object>)data;


            BeginTrans();
            Func<object> invoke = () =>
                {
                    return mds.DoPost(metaup, up, info.MetaUID, datalist, TokenPayLoad.ID, ComFunc.nvl(TokenPayLoad["username"]), ClientInfo.IP, BoolStd.IsNotBoolThen(Configs["Is_UseLocal"]));
                };
            var rtn = ParentEventCall(up, info.s_uid, "E02", invoke);
            CommitTrans();
            return rtn;
        }
        [EWRAEmptyValid("data")]
        [EWRARoute("delete", "/s_table/{id}")]
        [EWRARouteDesc("删除数据")]
        [EWRAAddInput("id", "string", "元数据表uid", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, false)]
        [EWRAAddInput("data", "array", @"待删除的数据列表，格式:
[
{
    column_name1:'值',
    column_name2:'值',
    .....
    column_nameN:'值',
}
]", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, false)]
        [EWRAOutputDesc("返回结果", @"根据http的状态码来识别，204标识操作成功，404表示操作识别未找到删除的资料")]
        public override bool delete(string id)
        {
            var data = PostDataD.data;

            if (!(data is IEnumerable<object>))
                return false;

            var metaup = DB.NewMetaUnitParameter();
            var up = DB.NewDBUnitParameter();
            var s = from t in DB.LamdaTable(up, "EXTEND_SINGLETABLE_OP", "a")
                    where (t.s_uid == id || t.S_Name == id)
                    select t;
            var list = s.GetQueryList(up);
            if (list.Count <= 0)
            {
                return false;
            }
            dynamic info = list.First();
            if (!IsValidBy("没有访问权限", () =>
            {
                return IsAuth(ComFunc.nvl(info.ActionAuth));
            }))
            {
                return false;
            }

            var datalist = (IEnumerable<object>)data;

            BeginTrans();
            Func<object> invoke = () =>
            {
                return mds.DoDelete(metaup, up, info.MetaUID, datalist, BoolStd.IsNotBoolThen(Configs["Is_UseLocal"]));
            };
            var rtn = ParentEventCall(up, info.s_uid, "E04", invoke);
            CommitTrans();
            return rtn;
        }
        [EWRAEmptyValid("data,ori_data")]
        [EWRARoute("patch", "/s_table/{id}")]
        [EWRARouteDesc("修改数据")]
        [EWRAAddInput("id", "string", "元数据表uid", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, false)]
        [EWRAAddInput("ori_data", "array", @"未修改的原始数据数据的条件，如果为file、picture类型,则需要先进行上传，再传入返回的文件路径，格式:
[
{
    column_name1:'值，如果为file、picture类型则值的格式内容为上传后的文件路径',
    column_name2:'值，如果为file、picture类型则值的格式内容为上传后的文件路径',
    .....
    column_nameN:'值，如果为file、picture类型则值的格式内容为上传后的文件路径',
}
]", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, false)]
        [EWRAAddInput("data", "array", @"待修改的数据列表，该数组中的每笔资料必须与ori_data中的下标和栏位都一致，如果为file、picture类型,则需要先进行上传，再传入返回的文件路径，格式:
[
{
    column_name1:'值，如果为file、picture类型则值的格式内容为上传后的文件路径',
    column_name2:'值，如果为file、picture类型则值的格式内容为上传后的文件路径',
    .....
    column_nameN:'值，如果为file、picture类型则值的格式内容为上传后的文件路径',
}
]", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, false)]
        [EWRAOutputDesc("返回结果", @"{
code:'success-成功，failed-失败',
msg:'提示信息'
}")]
        public override object patch(string id)
        {
            var data = PostDataD.data;
            var ori_data = PostDataD.ori_data;
            if (!(data is IEnumerable<object>) || !(ori_data is IEnumerable<object>))
            {
                return new
                {
                    code = "failed",
                    msg = "参数格式不正确",
                };
            }

            var metaup = DB.NewMetaUnitParameter();
            var up = DB.NewDBUnitParameter();
            var s = from t in DB.LamdaTable(up, "EXTEND_SINGLETABLE_OP", "a")
                    where (t.s_uid == id || t.S_Name == id)
                    select t;
            var list = s.GetQueryList(up);
            if (list.Count <= 0)
            {
                return false;
            }
            dynamic info = list.First();
            if (!IsValidBy("没有访问权限", () =>
            {
                return IsAuth(ComFunc.nvl(info.ActionAuth));
            }))
            {
                return false;
            }

            var datalist = (IEnumerable<object>)data;
            var ori_datalist = (IEnumerable<object>)ori_data;

            BeginTrans();
            Func<object> invoke = () =>
            {
                return mds.DoPatch(metaup, up, info.MetaUID, datalist, ori_datalist, TokenPayLoad.ID, ComFunc.nvl(TokenPayLoad["username"]), ClientInfo.IP, BoolStd.IsNotBoolThen(Configs["Is_UseLocal"]));
            };
            var rtn = ParentEventCall(up, info.s_uid, "E03", invoke);
            CommitTrans();
            return rtn;
        }
        [EWRARoute("post", "/s_table/{id}/upload")]
        [EWRAEmptyValid("file_name,file_length,file_content")]
        [EWRARouteDesc("上传文件")]
        [EWRAAddInput("file_name", "string", "文件名称", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, false)]
        [EWRAAddInput("file_length", "double", "文件大小", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, false)]
        [EWRAAddInput("file_content", "string", "文件内容，base64加密", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, false)]
        [EWRAOutputDesc("返回结果", @"{
code:'success-成功，failed-失败',
msg:'提示信息',
upload_path:'上传成功后返回的文档路径'
}")]
        object Upload(string id)
        {
            var up = DB.NewMetaUnitParameter();
            var s = from t in DB.LamdaTable(up, "EXTEND_SINGLETABLE_OP", "a")
                    where (t.s_uid == id || t.S_Name == id)
                    select t;
            var list = s.GetQueryList(up);
            if (list.Count <= 0)
            {
                return new
                {
                    code = "failed",
                    msg = "设定资料不存在"
                };
            }
            dynamic info = list.First();
            if (!IsValidBy("没有访问权限", () =>
            {
                return IsAuth(ComFunc.nvl(info.ActionAuth));
            }))
            {
                return null;
            }

            string file_name = ComFunc.nvl(PostDataD.file_name);
            long file_length = Int64Std.IsNotInt64Then(PostDataD.file_length);
            string file_content = ComFunc.nvl(PostDataD.file_content).Replace(" ", "+");
            var is_keep_filename = BoolStd.IsNotBoolThen(PostDataD.is_keep_filename);

            return FileHelper.DoUploadFile(file_name, file_length, file_content, is_keep_filename);
        }
        [EWRARoute("get", "/s_table/{id}/dl")]
        [EWRAEmptyValid("path")]
        [EWRARouteDesc("下载文件")]
        [EWRAAddInput("path", "string", "文件路径，使用urlcode编码", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.QueryString, false)]
        [EWRAOutputDesc("返回结果", @"{
code:'success-成功，failed-失败',
msg:'提示信息',
filetype:'文件的content-type类型'
filename:'文件名称',
filelength:'文件长度',
file:'文件内容，采用base64加密'
}")]
        object DownLoad(string id)
        {
            SetCacheEnable(false);
            var up = DB.NewMetaUnitParameter();
            var s = from t in DB.LamdaTable(up, "EXTEND_SINGLETABLE_OP", "a")
                    where (t.s_uid == id || t.S_Name == id)
                    select t;
            var list = s.GetQueryList(up);
            if (list.Count <= 0)
            {
                return new
                {
                    code = "failed",
                    msg = "设定资料不存在"
                };
            }
            dynamic info = list.First();
            if (!IsValidBy("没有访问权限", () =>
            {
                return IsAuth(ComFunc.nvl(info.ActionAuth));
            }))
            {
                return null;
            }
            string path = ComFunc.UrlDecode(QueryStringD.path);
            return FileHelper.DoDownLoad(path);
        }
        [EWRARoute("post", "/s_table/{id}/export")]
        [EWRARouteDesc("导出")]
        [EWRAAddInput("id", "string", "动态功能的uid", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, false)]
        [EWRAAddInput("column_select", "string", @"选择的栏位，多个栏位由逗号分隔，为空时则为动态功能中的设定的全部栏位", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, true)]
        [EWRAAddInput("xxx", "string", "动态功能中设定的查询条件参数", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.QueryString, true)]
        [EWRAOutputDesc("返回结果", @"如果是授权无效的情况下，返回400错，其它情况的返回结果集（状态为200）如下：{
code:'success-成功，failed-失败',
msg:'提示信息',
filetype:'文件的content-type类型',
filename:'文件名称',
filelength:'文件长度',
file:'文件内容，采用base64加密'
}")]
        object ExportExcel(string id)
        {
            string column_select = ComFunc.nvl(PostDataD.column_select);
            var column_select_arr = column_select.Split(",", StringSplitOptions.RemoveEmptyEntries);

            var up = DB.NewMetaUnitParameter();
            #region 检核
            var s = from t in DB.LamdaTable(up, "EXTEND_SINGLETABLE_OP", "a")
                    where (t.s_uid == id || t.S_Name == id)
                    select t;
            var list = s.GetQueryList(up);
            if (list.Count <= 0)
            {
                return new
                {
                    code = "failed",
                    msg = "设定资料不存在"
                };
            }
            dynamic info = list.First();
            if (!IsValidBy("没有访问权限", () =>
            {
                return IsAuth(ComFunc.nvl(info.ActionAuth));
            }))
            {
                return null;
            }
            var metainfo = (from t in DB.LamdaTable(up, "EXTEND_METADATA", "a")
                            where t.MetaUID == info.MetaUID && t.IsCreated == 1
                            select new
                            {
                                table_name = t.MetaName
                            }).GetQueryList(up);
            if (metainfo.Count <= 0)
            {
                return new
                {
                    code = "failed",
                    msg = "元数据表不存在，无法继续进行操作"
                };
            }
            #endregion

            Func<object> invoke = () =>
            {
                #region 抓取资料
                var table_name = ComFunc.nvl(metainfo.First().GetValue("table_name"));
                //组织查询表达式
                FrameDLRObject express = FrameDLRObject.CreateInstance($@"{{
$acttype : 'Query',
$orderby : 'sort_no',
$table:'{table_name}',
sort_no:true
                }}", EFFC.Frame.Net.Base.Constants.FrameDLRFlags.SensitiveCase);
                #region 获取查询条件信息
                var conditionlist = (from t in DB.LamdaTable(up, "EXTEND_SINGLETABLE_OP_CONDITIONS", "a")
                                     join t2 in DB.LamdaTable(up, "EXTEND_METADATA_COLUMNS", "b").LeftJoin() on t.S_ColumnName equals t2.MetaColumnName
                                     where t.S_UID == info.S_UID && t2.MetaUID == info.MetaUID
                                     select new
                                     {
                                         op = t.S_ConditionOP,
                                         column_name = t.S_ColumnName,
                                         parameter_name = t.S_Parameter,
                                         data_type = t2.MetaDataType
                                     }).GetQueryList(up);
                FrameDLRObject where_express = FrameDLRObject.CreateInstance(FrameDLRFlags.SensitiveCase);
                foreach (dynamic citem in conditionlist)
                {
                    if (ComFunc.nvl(QueryString[citem.parameter_name]) == "") continue;
                    var value = ConvertConditionValue(citem.data_type, ComFunc.nvl(QueryString[citem.parameter_name]));
                    FrameDLRObject exp = where_express.GetValue(citem.column_name);
                    if (exp == null)
                    {
                        exp = FrameDLRObject.CreateInstance(FrameDLRFlags.SensitiveCase);
                    }
                    switch (citem.op)
                    {
                        case "like":
                            exp.SetValue("$like", value);
                            where_express.SetValue(citem.column_name, exp);
                            break;
                        case "=":
                            where_express.SetValue(citem.column_name, value);
                            break;
                        case ">":
                            exp.SetValue("$gt", value);
                            where_express.SetValue(citem.column_name, exp);
                            break;
                        case ">=":
                            exp.SetValue("$gte", value);
                            where_express.SetValue(citem.column_name, exp);
                            break;
                        case "<":
                            exp.SetValue("$lt", value);
                            where_express.SetValue(citem.column_name, exp);
                            break;
                        case "<=":
                            exp.SetValue("$lte", value);
                            where_express.SetValue(citem.column_name, exp);
                            break;
                    }
                }
                if (where_express.Items.Count > 0)
                {
                    express.SetValue("$where", where_express);
                }
                #endregion
                #region 组织select栏位
                var columns = (from t in DB.LamdaTable(up, "EXTEND_SINGLETABLE_OP_COLUMNS", "a")
                               orderby t.S_Sort_Num
                               where t.S_UID == info.S_UID
                               select new
                               {
                                   column_name = t.S_ColumnName,
                                   column_desc = t.S_ColumnDesc
                               }).GetQueryList(up);
                var excel_column_array = new List<string>();
                var excel_header_array = new List<string>();
                foreach (dynamic item in columns)
                {
                    if (column_select_arr.Length <= 0
                        || column_select_arr.Contains((string)ComFunc.nvl(item.column_name)))
                    {
                        excel_column_array.Add(item.column_name);
                        excel_header_array.Add(item.column_desc);
                        express.SetValue(item.column_name, true);
                    }
                }

                var result = DB.Excute(up, express, false);
                #endregion
                #endregion

                #region 生成excel
                byte[] bytes = GenerateExcel(up, info.MetaUID, excel_column_array.ToArray(), excel_header_array.ToArray(), result.QueryData<FrameDLRObject>());
                #endregion


                return new
                {
                    code = "success",
                    msg = "",
                    filetype = ResponseHeader_ContentType.Map("xlsx"),
                    filename = $"{info.S_Name}_{DateTime.Now.ToString("yyyyMMdd")}.xlsx",
                    filelength = bytes.Length,
                    file = ComFunc.Base64Code(bytes)
                };
            };
            return ParentEventCall(up, info.s_uid, "E05", invoke);
        }
        [EWRARoute("post", "/s_table/{id}/export_template")]
        [EWRARouteDesc("导出模板")]
        [EWRAAddInput("id", "string", "动态功能的uid", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, false)]
        [EWRAAddInput("column_select", "string", @"选择的栏位，多个栏位由逗号分隔，为空时则为动态功能中的设定的全部栏位", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, true)]
        [EWRAAddInput("xxx", "string", "动态功能中设定的查询条件参数", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.QueryString, true)]
        [EWRAOutputDesc("返回结果", @"如果是授权无效的情况下，返回400错，其它情况的返回结果集（状态为200）如下：{
code:'success-成功，failed-失败',
msg:'提示信息',
filetype:'文件的content-type类型',
filename:'文件名称',
filelength:'文件长度',
file:'文件内容，采用base64加密'
}")]
        object ExportExcelTemplate(string id)
        {
            string column_select = ComFunc.nvl(PostDataD.column_select);
            var column_select_arr = column_select.Split(",", StringSplitOptions.RemoveEmptyEntries);

            var up = DB.NewMetaUnitParameter();
            #region 检核
            var s = from t in DB.LamdaTable(up, "EXTEND_SINGLETABLE_OP", "a")
                    where (t.s_uid == id || t.S_Name == id)
                    select t;
            var list = s.GetQueryList(up);
            if (list.Count <= 0)
            {
                return new
                {
                    code = "failed",
                    msg = "设定资料不存在"
                };
            }
            dynamic info = list.First();
            if (!IsValidBy("没有访问权限", () =>
            {
                return IsAuth(ComFunc.nvl(info.ActionAuth));
            }))
            {
                return null;
            }
            var metainfo = (from t in DB.LamdaTable(up, "EXTEND_METADATA", "a")
                            where t.MetaUID == info.MetaUID && t.IsCreated == 1
                            select new
                            {
                                table_name = t.MetaName
                            }).GetQueryList(up);
            if (metainfo.Count <= 0)
            {
                return new
                {
                    code = "failed",
                    msg = "元数据表不存在，无法继续进行操作"
                };
            }
            #endregion

            #region 抓取栏位信息
            var columns = (from t in DB.LamdaTable(up, "EXTEND_SINGLETABLE_OP_COLUMNS", "a")
                           orderby t.S_Sort_Num
                           where t.S_UID == info.S_UID
                           select new
                           {
                               column_name = t.S_ColumnName,
                               column_desc = t.S_ColumnDesc
                           }).GetQueryList(up);
            var excel_column_array = new List<string>();
            var excel_header_array = new List<string>();
            foreach (dynamic item in columns)
            {
                if (column_select_arr.Length <= 0
                    || column_select_arr.Contains((string)ComFunc.nvl(item.column_name)))
                {
                    excel_column_array.Add(item.column_name);
                    excel_header_array.Add(item.column_desc);
                }
            }
            #endregion

            #region 生成excel
            byte[] bytes = GenerateExcel(up, info.MetaUID, excel_column_array.ToArray(), excel_header_array.ToArray(), new List<FrameDLRObject>());
            #endregion


            return new
            {
                code = "success",
                msg = "",
                filetype = ResponseHeader_ContentType.Map("xlsx"),
                filename = $"{info.S_Name}_{DateTime.Now.ToString("yyyyMMdd")}.xlsx",
                filelength = bytes.Length,
                file = ComFunc.Base64Code(bytes)
            };
        }
        [EWRARoute("post", "/s_table/{id}/import")]
        [EWRARouteDesc("导入")]
        [EWRAAddInput("id", "string", "动态功能的uid", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, false)]
        [EWRAAddInput("file_name", "string", "文件名称", "无默认值", RestInputPosition.PostData, true)]
        [EWRAAddInput("file_content", "string", "文件内容，base64加密串", "无默认值", RestInputPosition.PostData, false)]
        [EWRAOutputDesc("返回结果", @"如果是授权无效的情况下，返回400错，其它情况的返回结果集（状态为200）如下：{
code:'success-成功，failed-失败',
msg:'提示信息'
}")]
        object ImportExcel(string id)
        {
            string filename = ComFunc.nvl(PostDataD.file_name);
            string filecontent = ComFunc.nvl(PostDataD.file_content);
            var data = Report.ReadExcel(filecontent, filename, 2);
            if (data == null) return new
            {
                code = "failed",
                msg = "文件内容不合法或为空"
            };

            if (data.Count <= 0)
            {
                return new
                {
                    code = "failed",
                    msg = "文件中没有数据"
                };
            }
            var metaup = DB.NewMetaUnitParameter();
            var up = DB.NewDBUnitParameter();
            #region 检核
            var s = from t in DB.LamdaTable(up, "EXTEND_SINGLETABLE_OP", "a")
                    where (t.s_uid == id || t.S_Name == id)
                    select t;
            var list = s.GetQueryList(up);
            if (list.Count <= 0)
            {
                return new
                {
                    code = "failed",
                    msg = "设定资料不存在"
                };
            }
            dynamic info = list.First();
            if (!IsValidBy("没有访问权限", () =>
            {
                return IsAuth(ComFunc.nvl(info.ActionAuth));
            }))
            {
                return null;
            }
            var metalist = (from t in DB.LamdaTable(up, "EXTEND_METADATA", "a")
                            where t.MetaUID == info.MetaUID && t.IsCreated == 1
                            select new
                            {
                                table_name = t.MetaName
                            }).GetQueryList(up);
            if (metalist.Count <= 0)
            {
                return new
                {
                    code = "failed",
                    msg = "元数据表不存在，无法继续进行操作"
                };
            }
            dynamic metainfo = metalist.First();
            #endregion

            #region 抓取栏位信息，进行栏位格式检查
            var ss = (from t in DB.LamdaTable(up, "EXTEND_SINGLETABLE_OP_COLUMNS", "a")
                      join t2 in DB.LamdaTable(up, "EXTEND_METADATA_COLUMNS", "b") on t.S_ColumnName equals t2.MetaColumnName
                      orderby t.S_Sort_Num
                      where t.S_UID == info.S_UID && t2.MetaUID == info.MetaUID
                      select new
                      {
                          column_name = t.S_ColumnName,
                          column_desc = t.S_ColumnDesc,
                          column_type = t2.MetaDataType
                      });
            var columns = ss.GetQueryList(up);
            var column_desc_map = columns.ToDictionary(k => ComFunc.nvl(k.GetValue("column_desc")), 
                v => new { column_name = ComFunc.nvl(v.GetValue("column_name")), column_type = ComFunc.nvl(v.GetValue("column_type")), });
            var datalist = new List<object>();
            foreach (var item in data)
            {
                FrameDLRObject dobj = FrameDLRObject.CreateInstance(FrameDLRFlags.SensitiveCase);
                if (item.Keys.Where(w => !column_desc_map.ContainsKey(w)).Count() > 0)
                {
                    return new
                    {
                        code = "failed",
                        msg = "导入的数据格式与模板不符"
                    };
                }

                foreach (var k in item.Keys)
                {
                    if (new string[] { "varchar", "nvarchar", "text","guid","random", "random_code" }.Contains(column_desc_map[k].column_type.ToLower()))
                    {
                        dobj.SetValue(column_desc_map[k].column_name, ComFunc.nvl(item.GetValue(k)));
                    }
                    else if (column_desc_map[k].column_type.ToLower() == "int")
                    {
                        dobj.SetValue(column_desc_map[k].column_name, IntStd.IsNotIntThen(item.GetValue(k)));
                    }
                    else if (column_desc_map[k].column_type.ToLower() == "numberic")
                    {
                        dobj.SetValue(column_desc_map[k].column_name, DoubleStd.IsNotDoubleThen(item.GetValue(k)));
                    }
                    else if (column_desc_map[k].column_type.ToLower() == "bit")
                    {
                        dobj.SetValue(column_desc_map[k].column_name, BoolStd.IsNotBoolThen(item.GetValue(k)));
                    }
                    else
                    {
                        dobj.SetValue(column_desc_map[k].column_name, item.GetValue(k));
                    }

                }

                datalist.Add(dobj);
            }
            #endregion
            var result = mds.DoPost(metaup, up, info.MetaUID, datalist, TokenPayLoad.ID, ComFunc.nvl(TokenPayLoad["username"]), ClientInfo.IP);

            return result;
        }

        [EWRARoute("post", "/s_table/{id}/event/{no}/eval")]
        [EWRARouteDesc("事件触发")]
        [EWRAAddInput("id", "string", "动态功能的uid", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, false)]
        [EWRAAddInput("no","string","事件编号","无默认值",RestInputPosition.Path,false)]
        [EWRAAddInput("this_data", "string", @"页面上当前编辑的行资料，先采用url编码，再采用base64编码，原数据格式:
{
    column_name1:'值',
    column_name2:'值',
    .....
    column_nameN:'值',
}", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, true)]
        [EWRAOutputDesc("返回结果", @"{
code:'success-成功，failed-失败',
msg:'提示信息'
}")]
        object CallEvent(string id,string no)
        {
            var data_str = ComFunc.nvl(PostDataD.this_data).Replace(" ", "+");
            var this_data_base64str = ComFunc.IsBase64Then(data_str);
            string this_data_str = ComFunc.UrlDecode(this_data_base64str);
            var this_data = FrameDLRObject.IsJsonThen(this_data_str);
            var up = DB.NewMetaUnitParameter();
            var events = (from t in DB.LamdaTable(up, "EXTEND_SINGLETABLE_OP_EVENTS", "a")
                          join t2 in DB.LamdaTable(up, "EXTEND_EVENTS", "b") on t.S_Event_No equals t2.EventNo
                          where t.S_UID == id && t2.EventNo == no
                          select new
                          {
                              t2.EventNo,
                              t2.EventAt,
                              t2.EventName
                          }).GetQueryList(up);
            if(events.Count <= 0)
            {
                return new
                {
                    code = "failed",
                    msg = "事件不存在"
                };
            }
            dynamic event_info = events.First();
            if(ComFunc.nvl(event_info.EventAt) != "New")
            {
                return new
                {
                    code = "failed",
                    msg = "事件触发时机不是“全新事件”不可执行"
                };
            }
            return DoCallEvent(up, no, this_data);
        }
        /// <summary>
        /// 执行事件
        /// </summary>
        /// <param name="up"></param>
        /// <param name="id"></param>
        /// <param name="this_data"></param>
        /// <returns></returns>
        private object DoCallEvent(UnitParameter up, string id, object this_data)
        {
            var list = (from t in DB.LamdaTable(up, "EXTEND_EVENTS", "a")
                        where t.EventNo == id
                        select new
                        {
                            no = t.EventNo,
                            name = t.EventName,
                            category = t.EventCategory,
                            type = t.EventType,
                            at = t.EventAt,
                            parent = t.
                            desc = t.EventDesc,
                            parameters = t.EventParameters
                        }).GetQueryList(up);
            if (list.Count <= 0)
            {
                return new
                {
                    code = "failed",
                    msg = "执行失败：事件设定不存在"
                };
            }
            dynamic info = list.First();
            var event_call = new EventsCall();
            var parameters = FrameDLRObject.IsJsonThen(info.parameters, null, FrameDLRFlags.SensitiveCase);
            if (parameters == null)
            {
                return new
                {
                    code = "failed",
                    msg = "执行失败：确少执行参数"
                };
            }
            string url = ComFunc.nvl(parameters.RequestUrl);
            string method = ComFunc.nvl(parameters.RequestMethod);
            FrameDLRObject query_string = ComFunc.nvl(parameters.RequestQueryString) == "" ? null : parameters.RequestQueryString;
            FrameDLRObject header = ComFunc.nvl(parameters.RequestHeader) == "" ? null : parameters.RequestHeaders;
            FrameDLRObject post_data = ComFunc.nvl(parameters.RequestPostData) == "" ? null : parameters.RequestPostData;
            var call_context = new EventsCall.EventsCallContext();
            call_context.RowData = ComFunc.Base64Code(FrameDLRObject.CreateInstance(this_data, FrameDLRFlags.SensitiveCase).tojsonstring());
            call_context.Login_ID = TokenPayLoad.ID;
            call_context.Login_Name = ComFunc.nvl(TokenPayLoad["username"]);
            if (url.StartsWith("~"))
            {
                return CallLocalLogic(url.Replace("~",""), method, header, query_string, post_data);
            }
            else
            {
                if (query_string != null)
                {
                    var qs = "";
                    foreach (var item in query_string.Items)
                    {
                        qs += $"{item.Key}={ComFunc.UrlEncode(item.Value)}&";
                    }
                    qs = qs.Length > 0 ? qs.Substring(0, qs.Length - 1) : "";
                    if (url.IndexOf("?") > 0)
                    {

                        url += $"&{qs}";
                    }
                    else
                    {
                        url += $"?{qs}";
                    }
                }
                string result = event_call.Send(url, method, call_context, header, post_data);
                if (result == null)
                {
                    return new
                    {
                        code = "failed",
                        msg = "执行失败：返回结果为空"
                    };
                }
                else if (result.StartsWith("Failed:"))
                {
                    return new
                    {
                        code = "failed",
                        msg = $"执行失败：{result}"
                    };
                }
                else
                {
                    return FrameDLRObject.IsJsonThen(result, null, FrameDLRFlags.SensitiveCase);
                }
            }
        }
        private object ParentEventCall(UnitParameter up,string s_uid,string parent_event_no,Func<object> invoke)
        {
            //获取绑定的事件
            var events = (from t in DB.LamdaTable(up, "EXTEND_SINGLETABLE_OP_EVENTS", "a")
                          join t2 in DB.LamdaTable(up, "EXTEND_EVENTS", "b") on t.S_Event_No equals t2.EventNo
                          where t.S_UID == s_uid && t2.ParentEventNo == parent_event_no
                          select new
                          {
                              t2.EventNo,
                              t2.EventAt,
                              t2.EventName
                          }).GetQueryList(up);
            var before_events = events.Where(w => w.EventAt == "Before");
            var after_events = events.Where(w => w.EventAt == "After");
            var replace_events = events.Where(w => w.EventAt == "Replace");
            //优先执行替换事件，多个替换事件只会执行第一个，
            if (replace_events != null && replace_events.Count() > 0)
            {
                dynamic eitem = replace_events.First();
                dynamic call_result = DoCallEvent(up, eitem.EventNo, null);
                if (call_result == null)
                {
                    return new
                    {
                        code = "failed",
                        msg = $"自定义事件{eitem.EventName}执行失败:无返回结果"
                    };
                }
                else
                {
                    if (ComFunc.nvl(call_result.code) != "success")
                    {
                        return new
                        {
                            code = "failed",
                            msg = $"自定义事件{eitem.EventName}执行失败:{call_result.msg}"
                        };
                    }
                    else
                    {
                        return call_result;
                    }
                }
            }

            if (before_events != null)
            {
                foreach (dynamic item in before_events)
                {
                    dynamic call_result = DoCallEvent(up, item.EventNo, null);
                    if (call_result == null)
                    {
                        return new
                        {
                            code = "failed",
                            msg = $"自定义事件{item.EventName}执行失败:无返回结果"
                        };
                    }
                    else
                    {
                        if (ComFunc.nvl(call_result.code) != "success")
                        {
                            return new
                            {
                                code = "failed",
                                msg = $"自定义事件{item.EventName}执行失败:{call_result.msg}"
                            };
                        }
                    }
                }
            }
            dynamic result = null;
            if(invoke != null)
            {
                result = invoke.Invoke();
            }
            if(result == null)
            {
                return new
                {
                    code = "failed",
                    msg = "执行出错"
                };
            }
            else
            {
                if(result is bool)
                {
                    if (!BoolStd.IsNotBoolThen(result))
                    {
                        return result;
                    }
                }
                else
                {
                    if (ComFunc.nvl(result.code) != "success")
                    {
                        return result;
                    }
                }
            }

            if (after_events != null)
            {
                foreach (dynamic item in after_events)
                {
                    dynamic call_result = DoCallEvent(up, item.EventNo, null);
                    if (call_result == null)
                    {
                        return new
                        {
                            code = "failed",
                            msg = $"自定义事件{item.EventName}执行失败:无返回结果"
                        };
                    }
                    else
                    {
                        if (ComFunc.nvl(call_result.code) != "success")
                        {
                            return new
                            {
                                code = "failed",
                                msg = $"自定义事件{item.EventName}执行失败:{call_result.msg}"
                            };
                        }
                    }
                }
            }

            return result;

        }
        private bool IsAuth(string action_auth)
        {
            if (action_auth == "") return true;
            var authfunctions = ComFunc.nvl(TokenPayLoad["Auth_Actions"]);
            return authfunctions.Split(',').Contains(action_auth);
        }
        private object ConvertConditionValue(string datatype, object v)
        {
            if (new string[] { "datetime" }.Contains(datatype.ToLower()))
            {
                return DateTimeStd.IsDateTimeThen(v, "yyyy-MM-dd HH:mm:ss");
            }
            else if (new string[] { "bit" }.Contains(datatype.ToLower()))
            {
                return BoolStd.ConvertTo(v, 1, 0);
            }
            else if (new string[] { "text", "picture", "file" }.Contains(datatype.ToLower()))
            {
                return "";
            }
            else
            {
                return v;
            }
        }

        private byte[] GenerateExcel(UnitParameter up, string meta_uid, string[] column_array, string[] header_names, List<FrameDLRObject> data)
        {
            var meta_columns = (from t in DB.LamdaTable(up, "EXTEND_METADATA_COLUMNS", "a")
                                where t.MetaUID == meta_uid
                                select new
                                {
                                    column_name = t.MetaColumnName,
                                    column_type = t.MetaDataType,
                                    column_ref = t.MetaReference
                                }).GetQueryList(up);

            var meta_columns_ref = meta_columns
                .Where(w => ComFunc.nvl(w.column_ref) != ""
                && new string[] { "varchar", "nvarchar" }.Contains((string)ComFunc.nvl(w.column_type))
                && column_array.Contains((string)ComFunc.nvl(w.column_name)));

            using (var ms = new MemoryStream())
            {
                IWorkbook workbook = new XSSFWorkbook();
                try
                {
                    ICellStyle headerStyle = workbook.CreateCellStyle();
                    //设置单元格上下左右边框线
                    headerStyle.BorderTop = BorderStyle.Thin;
                    headerStyle.BorderBottom = BorderStyle.Thin;
                    headerStyle.BorderLeft = BorderStyle.Thin;
                    headerStyle.BorderRight = BorderStyle.Thin;
                    headerStyle.FillPattern = FillPattern.SolidForeground;    //设置填充方案
                    headerStyle.FillForegroundColor = IndexedColors.Grey25Percent.Index;  //设置填充颜色

                    //文字水平和垂直对齐方式
                    headerStyle.Alignment = HorizontalAlignment.Center;
                    headerStyle.VerticalAlignment = VerticalAlignment.Center;

                    ICellStyle dataStyle = workbook.CreateCellStyle();
                    //设置单元格上下左右边框线
                    dataStyle.BorderTop = BorderStyle.Dotted;
                    dataStyle.BorderBottom = BorderStyle.Dotted;
                    dataStyle.BorderLeft = BorderStyle.Dotted;
                    dataStyle.BorderRight = BorderStyle.Dotted;
                    //文字水平和垂直对齐方式
                    dataStyle.Alignment = HorizontalAlignment.Center;
                    dataStyle.VerticalAlignment = VerticalAlignment.Center;


                    ISheet sheetData = workbook.CreateSheet("数据");
                    IRow row = sheetData.CreateRow(0);
                    for (var i = 0; i < header_names.Length; i++)
                    {
                        var cell = row.CreateCell(i);
                        cell.CellStyle = headerStyle;
                        cell.SetCellValue(header_names[i]);
                    }
                    var index = 1;
                    foreach (var item in data)
                    {
                        var r = sheetData.CreateRow(index);
                        for (var i = 0; i < column_array.Length; i++)
                        {
                            var cell = r.CreateCell(i);
                            cell.CellStyle = dataStyle;
                            cell.SetCellType(CellType.String);
                            var v = item.GetValue(column_array[i]);
                            if (v is DateTime)
                            {
                                cell.SetCellValue(DateTimeStd.IsDateTimeThen(v, "yyyy-MM-dd HH:mm:ss"));
                            }
                            else
                            {
                                cell.SetCellValue(ComFunc.nvl(v));
                            }
                        }
                        index++;
                    }
                    AutoFitColumnWidth(sheetData, column_array);



                    foreach (dynamic mcr in meta_columns_ref)
                    {
                        RefExpress.RefExpressResult refResult = ref_express.ParseExpress(mcr.column_ref);
                        if (refResult == null || string.IsNullOrEmpty(refResult.TableName)) continue;
                        FrameDLRObject express = FrameDLRObject.CreateInstance($@"{{
$acttype : 'Query',
$orderby : 'sort_no',
$table:'{refResult.TableName}'
                }}", EFFC.Frame.Net.Base.Constants.FrameDLRFlags.SensitiveCase);
                        if (!string.IsNullOrEmpty(refResult.KeyColumn))
                        {
                            express.SetValue(refResult.KeyColumn, true);
                        }
                        foreach (var c in refResult.ShowColumns)
                        {
                            express.SetValue(c, true);
                        }
                        if (refResult.Filter.Count > 0)
                        {
                            var op_map = new Dictionary<string, string>();
                            op_map.Add(":", "$like");
                            op_map.Add("=", "$eq");
                            op_map.Add(">", "$gt");
                            op_map.Add(">=", "$gte");
                            op_map.Add("<", "$lt");
                            op_map.Add("<=", "$lte");
                            FrameDLRObject where = FrameDLRObject.CreateInstance(FrameDLRFlags.SensitiveCase);

                            foreach (var witem in refResult.Filter)
                            {
                                FrameDLRObject op_express = FrameDLRObject.CreateInstance(FrameDLRFlags.SensitiveCase);
                                op_express.SetValue(op_map[witem.Value.Op], witem.Value.Value);


                                where.SetValue(witem.Key, op_express);
                            }

                            express.SetValue("$where", where);
                        }

                        var option_data = DB.Excute(up, express, false).QueryData<FrameDLRObject>();
                        var column_desc_map = (from t in DB.LamdaTable(up, "EXTEND_METADATA_COLUMNS", "a")
                                               join t2 in DB.LamdaTable(up, "EXTEND_METADATA", "b") on t.MetaUID equals t2.MetaUID
                                               where t2.MetaName == refResult.TableName
                                               select new
                                               {
                                                   column_name = t.MetaColumnName,
                                                   column_desc = t.MetaColumnDesc
                                               }).GetQueryList(up).ToDictionary(k => ComFunc.nvl(k.GetValue("column_name")), v => ComFunc.nvl(v.GetValue("column_desc")));

                        string column_name = ComFunc.nvl(mcr.column_name);

                        CreateRef4WorkBook(workbook, sheetData, column_array.ToList().IndexOf(column_name), 1, refResult.TableName, refResult.KeyColumn, option_data, column_desc_map);
                    }
                    workbook.Write(ms);
                }
                finally
                {
                    workbook.Close();
                }

                return ms.ToArray();
            }
        }
        /// <summary>
        /// 给sheetData创建下拉列表
        /// </summary>
        /// <param name="workbook"></param>
        /// <param name="sheetData"></param>
        /// <param name="validCellIndex">dataSheet中生效的cell位置，从1开始</param>
        /// <param name="validStartRow">dataSheet中生效起始行</param>
        /// <param name="sheetName">引用sheet的名称</param>
        /// <param name="keyColumnName">下拉框中有效值的栏位名称，该栏位会放在引用sheet中的第一列</param>
        /// <param name="data">下拉框的数据集</param>
        /// <param name="column_desc_map">栏位与header名称的对应关系</param>
        private void CreateRef4WorkBook(IWorkbook workbook, ISheet sheetData, int validCellIndex, int validStartRow, string sheetName, string keyColumnName, List<FrameDLRObject> data, Dictionary<string, string> column_desc_map)
        {
            ISheet sheetRef = workbook.CreateSheet(sheetName);//名为ref的工作表
            var index = 0;
            var r = sheetRef.CreateRow(index);
            var j = 0;
            if (!string.IsNullOrEmpty(keyColumnName))
            {
                r.CreateCell(j).SetCellValue(column_desc_map.ContainsKey(keyColumnName) ? column_desc_map[keyColumnName] : keyColumnName);
                j++;
                if (data.Count > 0)
                {
                    foreach (var k in data.First().Keys)
                    {
                        if (k == keyColumnName) continue;
                        r.CreateCell(j).SetCellValue(column_desc_map.ContainsKey(k) ? column_desc_map[k] : k);
                        j++;
                    }
                }
                index++;
            }



            foreach (var d in data)
            {
                r = sheetRef.CreateRow(index);
                j = 0;
                if (!string.IsNullOrEmpty(keyColumnName))
                {
                    var v = d.GetValue(keyColumnName);
                    if (v is DateTime)
                    {
                        r.CreateCell(j).SetCellValue(DateTimeStd.IsDateTimeThen(v, "yyyy-MM-dd HH:mm:ss"));
                    }
                    else
                    {
                        r.CreateCell(j).SetCellValue(ComFunc.nvl(v));
                    }
                    j++;
                }
                foreach (var k in d.Keys)
                {
                    if (k == keyColumnName) continue;

                    var v = d.GetValue(k);
                    if (v is DateTime)
                    {
                        r.CreateCell(j).SetCellValue(DateTimeStd.IsDateTimeThen(v, "yyyy-MM-dd HH:mm:ss"));
                    }
                    else
                    {
                        r.CreateCell(j).SetCellValue(ComFunc.nvl(v));
                    }
                    j++;
                }
                index++;
            }
            if (data.Count > 0)
            {
                IName range = workbook.CreateName();//创建一个命名公式
                range.RefersToFormula = sheetName + "!$A$2:$A$" + (data.Count + 1);//公式内容，就是上面的区域
                range.NameName = "sectionName_" + sheetName;//公式名称，可以在"公式"-->"名称管理器"中看到

                CellRangeAddressList regions = new CellRangeAddressList(validStartRow, 65535, validCellIndex, validCellIndex);//约束范围：B1到B65535
                XSSFDataValidationHelper helper = new XSSFDataValidationHelper((XSSFSheet)sheetData);//获得一个数据验证Helper
                IDataValidation validation = helper.CreateValidation(helper.CreateFormulaListConstraint(range.NameName), regions);//创建一个特定约束范围内的公式列表约束（即第一节里说的"自定义"方式）
                validation.CreateErrorBox("错误", "请按右侧下拉箭头选择!");//不符合约束时的提示
                validation.ShowErrorBox = true;//显示上面提示 = True
                sheetData.AddValidationData(validation);//添加进去
                sheetData.ForceFormulaRecalculation = true;
            }
        }
        /// <summary>
        /// 列宽度自适应
        /// </summary>
        /// <param name="sheet"></param>
        /// <param name="column_array"></param>
        private void AutoFitColumnWidth(ISheet sheet, string[] column_array)
        {
            //获取当前列的宽度，然后对比本列的长度，取最大值
            for (int columnNum = 0; columnNum <= column_array.Length; columnNum++)
            {
                sheet.AutoSizeColumn(columnNum);//先来个常规自适应

                int columnWidth = sheet.GetColumnWidth(columnNum) / 256;
                for (int rowNum = 1; rowNum <= sheet.LastRowNum; rowNum++)
                {
                    IRow currentRow;
                    //当前行未被使用过
                    if (sheet.GetRow(rowNum) == null)
                    {
                        currentRow = sheet.CreateRow(rowNum);
                    }
                    else
                    {
                        currentRow = sheet.GetRow(rowNum);
                    }

                    if (currentRow.GetCell(columnNum) != null)
                    {
                        ICell currentCell = currentRow.GetCell(columnNum);
                        int length = Encoding.Default.GetBytes(currentCell.ToString()).Length;
                        if (columnWidth < length)
                        {
                            columnWidth = length;
                        }
                    }
                }
                sheet.SetColumnWidth(columnNum, columnWidth * 300);//一般是*256，我给加宽一丢丢
            }
        }
    }
}
